include("jclass.events");
use("jclass.events");

var XXX = 2;

namespace("jclass.net")
({
    RequestType : jClass({
        static : {
            ASYNCHRONOUS : true,
            SYNCHRONOUS : false
        }
    }),
    DataFormat : jClass({
        static : {
            // Specifies that downloaded data is received as raw binary data.
            BINARY : "binary",
            // Specifies that downloaded data is received as text.
            TEXT : "text",
            // Specifies that downloaded data is received as URL-encoded variables.
            VARIABLES : "variables",
            // Specifies that downloaded data is received JSON serialized object
            JSON : "json",
            // Specifies that downloaded data is received as XML
            XML : "xml",
            // Specifies that downloaded data is received as zip packed file.
            PACKED : "packed"
        }
    }),
    RequestMethod : jClass({
        static : {
            DELETE : "delete",
            GET : "get",
            HEAD : "head",
            OPTIONS : "options",
            POST : "post",
            PUT : "put"
        }
    }),
    URLRequest : jClass({
        constructor : function(address, type) {
            if (address) this.url = address;
            if (type !== undefined) async = type
        },
        public : {
            /**
             * Specifies the way the response should be formatted
             */
            format : "binary",
            /**
             * Specifies whether authentication requests should be handled (true or not (false) for this request.
             */
            authenticate : false,
            /**
             * Specifies whether successful response data should be cached for this request.
             */
            cacheResponse : false,
            /**
             * Specifies whether the call should be made asynchronous or not
             */
            async : true,
            /**
             * The MIME content type of the content in the the data property.
             */
            contentType : '',
            /**
             * The array of HTTP request headers to be appended to the HTTP request.
             */
            requestHeaders : new Array(),
            /**
             * An object containing data to be transmitted with the URL request.
             */
            data : undefined,
            /**
             * Controls the HTTP form submission method.
             */
            method : 'get',
            /**
             * The URL to be requested.
             */
            url : GetSet(function() { return _url; }, function(address) { _url = address }),
            /**
             * Specifies whether the local cache should be consulted before this URLRequest fetches data.
             */
            useCache : true
        }
    }),
    RequestHeader : jClass({
        constructor : function(reqname, reqvalue) {
            this.name = reqname;
            this.value = reqvalue;
        },
        public : {
            name : '',
            value : undefined
        }
    }),
   ProgressEvent : jClass.extend(Event).implement(IEvent)({
      static : {
          PROGRESS : "progress"
      },
      constructor : function(totalBytes, loaded, netTarget) {
          this.type = "progress";
          
          this.bytesTotal = totalBytes;
          this.bytesLoaded = loaded;
          this.target = netTarget;
      },
      public : {
          bytesTotal : 0,
          bytesLoaded : 0,
          target : undefined
      }
   })
});

namespace("jclass.net")
({
    URLLoader : jClass.extend(EventDispatcher)({
        constructor : function(request) {
            if (request) _request = request;
            _instance = this;
        },
        private : {
            _instance : undefined,
            _request : undefined,
            _xReq : undefined,
            _progress : undefined,

            getXMLHttpObj : function() {
                if(typeof(XMLHttpRequest)!='undefined') {
                    return new XMLHttpRequest();
                }
                var axO = ['Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.4.0', 'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP', 'Microsoft.XMLHTTP'], i;
                for (i = 0; i < axO.length; i++) {
                    try{
                        return new ActiveXObject(axO[i]);
                    }catch(e){}
                }
                return null;
            },
            doRequest : function() {
                if (_request === undefined) {
                    this.DispatchEvent(new Event(Event.ERROR, "No URLRequest object passed"));
                    return;
                }
                var headers = _request.requestHeaders;
                 _progress = new jclass.net.ProgressEvent(_bytesTotal, _bytesLoaded, _instance);

                _xReq = getXMLHttpObj();
                // add custom headers
                for (var i = 0; i < headers.length; i++) {
                    if (headers[i] && headers[i].isInstanceOf(jclass.net.RequestHeader)) {
                        try {
                            _xReq.setRequestHeader(headers[i].name, headers[i].value);
                        } catch(ex) {
                            console.log(ex)
                        }
                    }
                }

                _xReq.open("GET", _request.url, _request.async);
                 _xReq.onreadystatechange = onReadyStateChange;
                _xReq.send();
                /**
                 * readyState
                 * responseText
                 * statusText
                 * status
                 * responseXML
                 * abort()
                 * getAllResponseHeaders()
                 * getResponseHeader()
                 * overrideMimeType()
                 * open = function(method,url,async,username,password)
                 * send = function(content)
                 * setRequestHeader = function(label,value)
                 * onreadystatechange()
                 */
                // xhReq.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2005 00:00:00 GMT");
                // header("Pragma: no-cache");
                //req.overrideMimeType('text/plain; charset=x-user-defined');
            },
            onReadyStateChange : function() {

                //readyState = 0 Uninitialized - open() has not bee called yet
                //readyState = 1 Loading - send() has not been called yet
                //readyState = 2 Loaded - send() has been called, headers and status are available
                //readyState = 3 Interactive - Downloading, responseText holds the partial data

                _responseStatusText = _xReq.statusText;
                _responseStatus = _xReq.status;

                if (_xReq.readyState == 2) {
                     if (_xReq.status == 404) {
                         _super.DispatchEvent(new Event(Event.ERROR, _xReq.status + " " + _xReq.statusText));
                        _xReq.abort();
                         return;
                     }
                     if (_xReq.status == 200) {
                         var headers = _xReq.getAllResponseHeaders().split("\n");
                            _responseHeaders = {};
                            for (var i = 0; i < headers.length; i++) {
                                var name = headers[i].substr(0, headers[i].indexOf(":"));
                                var value = _xReq.getResponseHeader(name);
                                if (value) {
                                    _responseHeaders[name] = value;
                                }
                            }
                     }
                } else if (_xReq.readyState == 3) {
                        _bytesTotal  = parseInt(_xReq.getResponseHeader('Content-Length'));
                        //_bytesLoaded = _xReq.responseText.length;
                    
                } else if (_xReq.readyState == 4) {
                     if (_xReq.status == 200) {
                            // console.log("4 Completed - Finished with all operations.");
                            _data = _xReq.responseText;
                            _bytesTotal = _progress.bytesTotal = _bytesLoaded = _progress.bytesLoaded = parseInt(_xReq.getResponseHeader('Content-Length'));
                            _super.DispatchEvent(_progress);
                            _super.DispatchEvent(new Event(Event.COMPLETE, _xReq.responseText));
                        }
                        return;
                }
                return;

                switch (_xReq.status) {
                    case 200: // ok
                        _bytesTotal = _progress.bytesTotal = parseInt(_xReq.getResponseHeader('Content-Length'));
                        _bytesLoaded = _progress.bytesLoaded = _xReq.responseText.length;
                        _data = _xReq.responseText;
                       // _super.DispatchEvent(_progress);
                        break;
                    case 404: // not found
                        _super.DispatchEvent(Event(Event.ERROR, "404 Page not found"));
                        _xReq.abort();
                        break;
                    case 304: // not modified
                        //console.log("not modified");
                        break;
                    default:
                        //console.log("ready state != 200 : ", _xReq.readyState)
                }
            },
            cleanUp : function() {
                _xReq = undefined;
                _progress = undefined;
            }
        },
        public : {
            bytesLoaded : Get(function() { return _bytesLoaded || 0 }),
            bytesTotal : Get(function() { return _bytesTotal || 0 }),
            data : Get(function() { return _data || '' }),
            dataFormat : Get(function() { return _dataFormat || 'text' }),

            responseHeaders :  Get(function() { return _responseHeaders || '' }),
            responseStatus : Get(function() { return _responseStatus || '' }),
            responseStatusText : Get(function() { return _responseStatusText || '' }),

            load : function(request) {
                if (request) _request = request;
                doRequest();
            }
        }
    })
});